import React, {
    PureComponent
} from 'react';

import {
    View,
    ViewStyle,
    StyleSheet,
    ImageSourcePropType
} from 'react-native';

import PropTypes from 'prop-types';

import uuId from 'uuid/v4';

import getRect from './../ListView/rect';

import Image,{
    FastImageSource
} from 'react-native-fast-image';

import default_pic from './img/m_pic.png';

interface Context {
    scroll?: Scroll
}

interface State {
    show: boolean,
    cover: boolean
}

interface Props {
    url: string,
    opacity: number,
    style?: ViewStyle|any,
    enableLazy:boolean,
    defaultSourceStyle?:ViewStyle|any,
    defaultSource?: ImageSourcePropType
}

interface Scroll {
    lazy: boolean,
    offsetY:Function,
    onLazyScroll: Function,
    removeLazyScroll: Function,
}

class RnImage extends PureComponent<Props, State> {
    url:string = ``;
    Ref: any = null;
    timer:any = null;
    imageId:string = ``;

    constructor(
        props: Props,
        context: Context
    ) {
        super(props);
        const {
            url,
            enableLazy
        } = props;

        const {
            lazy = false
        } = this.ctx(context);

        this.url = url;

        this.state = {
            cover: true,
            show: enableLazy ? !lazy : true
        }
    }

    static defaultProps = {
        opacity: 0,
        enableLazy:true
    }

    static contextTypes = {
        scroll: PropTypes.shape({
            lazy: PropTypes.bool,
            onLazyScroll: PropTypes.func,
            removeLazyScroll:PropTypes.func
        })
    }

    _flag: boolean = false;

    componentDidMount() {
        const {
            enableLazy
        } = this.props;

        if(enableLazy) {
            this.imageId = uuId();
            this._onInit();
        }
    }

    componentDidUpdate() {
        const {
            url
        } = this.props;

        if(url!== this.url) {
            this.url = url;
            this.setState({
                cover:true
            })
        }
    }

    componentWillUnmount() {
        const {
            enableLazy
        } = this.props;

        if(this.timer) {
            clearTimeout(this.timer);
        }

        if(enableLazy) {
            this._removeListen();
        }
    }

    ctx = (context?: Context): Scroll => {
        const {
            scroll
        } = context || this.context;
        return scroll || {};
    }

    _onInit = () => {
        const {
            lazy = false,
            onLazyScroll
        } = this.ctx();

        //监听滚动
        if (lazy) {
            onLazyScroll(this.imageId,this._onScroll);
            this.timer = setTimeout(this._onScroll,600);
        }
    }

    private _onScroll = async () => {
        const {
            show
        } = this.state;

        const {
            lazy = false,
            offsetY
        } = this.ctx();

        if (!lazy || show || this._flag) {
            return false
        }

        this._flag = true;

        const {
            top
        } = await getRect(this.Ref);

        const _offsetY = offsetY() || 0;

        this._flag = false;

        if (top <= 0 || top > _offsetY * 2) {
            return false
        }

        this._removeListen();

        this.setState({
            show: true
        })
    }

    _removeListen = () => {
        const {
            lazy = false,
            removeLazyScroll
        } = this.ctx();

        if (lazy) {
            removeLazyScroll(this.imageId)
        }
    }

    get source(): FastImageSource {
        const {
            url
        } = this.props;

        return {
            uri: url
        }
    }

    get defaultSource() {
        const {
            defaultSource
        } = this.props;
        return defaultSource || default_pic;
    }

    get maskStyle(): any {
        const {
            opacity
        } = this.props;
        return [StyleSheet.absoluteFill, {
            backgroundColor: `rgba(0,0,0,${opacity})`
        }]
    }

    private onLoadStart = () => {
        this.setState({
            cover: true
        })
    }

    private onLoadSuccess = () => {
        this.setState({
            cover: false
        })
    }

    get AnimatedImage() {
        const {
            cover
        } = this.state;

        const {
            defaultSourceStyle
        } = this.props;

        if(!cover) {
            return null
        }

        return (
            <View style={styles.defaultImageStyle}>
                <Image
                    resizeMode="contain"
                    source={this.defaultSource}
                    style={[styles.defaultImage,defaultSourceStyle]}
                />
            </View>
        )
    }

    render() {
        const {
            show
        } = this.state;

        const {
            style,
            children
        } = this.props;

        const _styles = [
            styles.container, style
        ]

        return (
            <View
                style={_styles}
                ref={e => this.Ref = e}
            >
                {show ? (
                    <Image
                        source={this.source}
                        onLoad={this.onLoadSuccess}
                        onLoadStart={this.onLoadStart}
                        style={StyleSheet.absoluteFill}
                    />
                ) : null }
                <View style={this.maskStyle} />
                {this.AnimatedImage}
                {children}
            </View>
        )
    }
}

export default RnImage;

const styles = StyleSheet.create({
    container: {
        overflow: `hidden`,
        backgroundColor:`#333`
    },

    defaultImage: {
        width:`90%`,
        height:`90%`
    },
    defaultImageStyle:{
        top:0,
        left:0,
        width:`100%`,
        height:`100%`,
        alignItems:`center`,
        position:`absolute`,
        justifyContent:`center`,
        backgroundColor: `#f6f6f6`
    }
}) as any;


